package com.cll.prototype.common.config.ratelimiter.impl;

import com.cll.prototype.common.config.ratelimiter.IRateLimiter;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.flogger.Flogger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 描述信息:
 * 使用google的guava实现限流
 * @author CLL
 * @version 1.0
 * @date 2020/11/1 8:34
 */
@Slf4j
@Component("guavaRateLimiter")
public class GuavaRateLimiter implements IRateLimiter {

    private static Cache<String, RateLimiter> caches = CacheBuilder.newBuilder()
            //在访问后1分钟清除
            .expireAfterAccess(1, TimeUnit.MINUTES)
            //最大值,超过这个值会清除掉最近没使用到的缓存
            .maximumSize(1024)
            .build();

    @Override
    public boolean applyAcquire(String key, int limitCount, int timePeriod) {
        double limitPerSec = limitCount * 1.0 / timePeriod;
        RateLimiter limiter;
        try {
            limiter = caches.get(key, () -> RateLimiter.create(limitPerSec));
        } catch (ExecutionException e) {
            log.error("****** 获取限流抛出执行异常: " + e.getMessage(), e);
            return false;
        }
        if (limiter != null){
            return limiter.tryAcquire(1, TimeUnit.SECONDS);
        } else {
            log.error("****** 获取限流令牌出现未知错误");
            return false;
        }
    }
}
